Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
0.00% |
0 / 1 |
|
50.00% |
7 / 14 |
CRAP | |
74.79% |
89 / 119 |
| AssetUpdater | |
0.00% |
0 / 1 |
|
50.00% |
7 / 14 |
77.45 | |
74.79% |
89 / 119 |
| __construct | |
100.00% |
1 / 1 |
1 | |
100.00% |
5 / 5 |
|||
| update | |
0.00% |
0 / 1 |
3.71 | |
57.14% |
4 / 7 |
|||
| setData | |
100.00% |
1 / 1 |
7 | |
100.00% |
26 / 26 |
|||
| setTags | |
100.00% |
1 / 1 |
4 | |
100.00% |
10 / 10 |
|||
| setCategories | |
100.00% |
1 / 1 |
4 | |
100.00% |
10 / 10 |
|||
| validateDateFormat | |
0.00% |
0 / 1 |
9.63 | |
29.41% |
5 / 17 |
|||
| getTagByCode | |
0.00% |
0 / 1 |
3.19 | |
33.33% |
3 / 9 |
|||
| getCategoryByCode | |
100.00% |
1 / 1 |
2 | |
100.00% |
9 / 9 |
|||
| removeTagsByCodes | |
100.00% |
1 / 1 |
2 | |
100.00% |
3 / 3 |
|||
| removeCategoriesByCodes | |
100.00% |
1 / 1 |
2 | |
100.00% |
3 / 3 |
|||
| setLocalized | |
0.00% |
0 / 1 |
3.14 | |
75.00% |
3 / 4 |
|||
| validateIsArrayOfScalar | |
0.00% |
0 / 1 |
10.40 | |
40.00% |
4 / 10 |
|||
| validateIsScalar | |
0.00% |
0 / 1 |
3.33 | |
66.67% |
2 / 3 |
|||
| validateIsBoolean | |
0.00% |
0 / 1 |
3.33 | |
66.67% |
2 / 3 |
|||
| <?php | |
| /* | |
| * This file is part of the Akeneo PIM Enterprise Edition. | |
| * | |
| * (c) 2015 Akeneo SAS (http://www.akeneo.com) | |
| * | |
| * For the full copyright and license information, please view the LICENSE | |
| * file that was distributed with this source code. | |
| */ | |
| namespace Akeneo\Asset\Component\Updater; | |
| use Akeneo\Asset\Component\Factory\AssetFactory; | |
| use Akeneo\Asset\Component\Model\AssetInterface; | |
| use Akeneo\Asset\Component\Model\CategoryInterface; | |
| use Akeneo\Asset\Component\Model\TagInterface; | |
| use Akeneo\Tool\Component\Classification\Repository\CategoryRepositoryInterface; | |
| use Akeneo\Tool\Component\Classification\Repository\TagRepositoryInterface; | |
| use Akeneo\Tool\Component\StorageUtils\Exception\ImmutablePropertyException; | |
| use Akeneo\Tool\Component\StorageUtils\Exception\InvalidObjectException; | |
| use Akeneo\Tool\Component\StorageUtils\Exception\InvalidPropertyException; | |
| use Akeneo\Tool\Component\StorageUtils\Exception\InvalidPropertyTypeException; | |
| use Akeneo\Tool\Component\StorageUtils\Exception\UnknownPropertyException; | |
| use Akeneo\Tool\Component\StorageUtils\Updater\ObjectUpdaterInterface; | |
| use Doctrine\Common\Util\ClassUtils; | |
| use Symfony\Component\PropertyAccess\PropertyAccess; | |
| use Symfony\Component\PropertyAccess\PropertyAccessor; | |
| /** | |
| * Updates and validates a asset | |
| * | |
| * @author Olivier Soulet <olivier.soulet@akeneo.com> | |
| */ | |
| class AssetUpdater implements ObjectUpdaterInterface | |
| { | |
| /** @var TagRepositoryInterface */ | |
| protected $tagRepository; | |
| /** @var CategoryRepositoryInterface */ | |
| protected $categoryRepository; | |
| /** @var AssetFactory */ | |
| protected $assetFactory; | |
| /** @var PropertyAccessor */ | |
| protected $accessor; | |
| /** | |
| * @param TagRepositoryInterface $tagRepository | |
| * @param CategoryRepositoryInterface $categoryRepository | |
| * @param AssetFactory $assetFactory | |
| */ | |
| public function __construct( | |
| TagRepositoryInterface $tagRepository, | |
| CategoryRepositoryInterface $categoryRepository, | |
| AssetFactory $assetFactory | |
| ) { | |
| $this->tagRepository = $tagRepository; | |
| $this->categoryRepository = $categoryRepository; | |
| $this->assetFactory = $assetFactory; | |
| $this->accessor = PropertyAccess::createPropertyAccessor(); | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function update($asset, array $data, array $options = []) | |
| { | |
| if (!$asset instanceof AssetInterface) { | |
| throw InvalidObjectException::objectExpected( | |
| ClassUtils::getClass($asset), | |
| AssetInterface::class | |
| ); | |
| } | |
| foreach ($data as $field => $item) { | |
| $this->setData($asset, $field, $item); | |
| } | |
| return $this; | |
| } | |
| /** | |
| * @param AssetInterface $asset | |
| * @param string $field | |
| * @param mixed $data | |
| * | |
| * @throws InvalidPropertyException | |
| * @throws UnknownPropertyException | |
| */ | |
| protected function setData(AssetInterface $asset, $field, $data) | |
| { | |
| switch ($field) { | |
| case 'tags': | |
| $this->validateIsArrayOfScalar($field, $data); | |
| $this->setTags($asset, $data); | |
| break; | |
| case 'categories': | |
| $this->validateIsArrayOfScalar($field, $data); | |
| $this->setCategories($asset, $data); | |
| break; | |
| case 'end_of_use': | |
| $this->validateDateFormat($field, $data); | |
| $asset->setEndOfUseAt(new \DateTime($data)); | |
| break; | |
| case 'localizable': | |
| $this->validateIsBoolean($field, $data); | |
| $this->setLocalized($asset, $data); | |
| break; | |
| case 'code': | |
| $this->validateIsScalar($field, $data); | |
| $this->accessor->setValue($asset, $field, $data); | |
| break; | |
| case 'description': | |
| $this->validateIsScalar($field, $data); | |
| $this->accessor->setValue($asset, $field, $data); | |
| break; | |
| default: | |
| throw UnknownPropertyException::unknownProperty($field); | |
| } | |
| } | |
| /** | |
| * It sets the tags by diff with existing tags and then remove other tags (due to doctrine UOW that does not | |
| * update link between the tags and the asset). | |
| * | |
| * @param AssetInterface $asset | |
| * @param array $data | |
| * | |
| * @throws InvalidPropertyException | |
| */ | |
| protected function setTags(AssetInterface $asset, array $data) | |
| { | |
| $newTags = $data; | |
| $tagCodes = $asset->getTagCodes(); | |
| if (!empty($tagCodes)) { | |
| $newTags = array_diff($data, $tagCodes); | |
| } | |
| foreach ($newTags as $tagCode) { | |
| $asset->addTag($this->getTagByCode($tagCode)); | |
| } | |
| if (!empty($tagCodes)) { | |
| $toRemoveTags = array_diff($tagCodes, $data); | |
| $this->removeTagsByCodes($asset, $toRemoveTags); | |
| } | |
| } | |
| /** | |
| * It sets the categories by diff with existing tags and then remove other categories (due to doctrine UOW that | |
| * does not update link between the categories and the asset). | |
| * | |
| * @param AssetInterface $asset | |
| * @param array $data | |
| * | |
| * @throws InvalidPropertyException | |
| */ | |
| protected function setCategories(AssetInterface $asset, array $data) | |
| { | |
| $newCategories = $data; | |
| $categoriesCode = $asset->getCategoryCodes(); | |
| if (!empty($categoriesCode)) { | |
| $newCategories = array_diff($newCategories, $categoriesCode); | |
| } | |
| foreach ($newCategories as $categoryCode) { | |
| $asset->addCategory($this->getCategoryByCode($categoryCode)); | |
| } | |
| if (!empty($categoriesCode)) { | |
| $categories = array_diff($categoriesCode, $data); | |
| $this->removeCategoriesByCodes($asset, $categories); | |
| } | |
| } | |
| /** | |
| * @param string $field | |
| * @param string $data | |
| * | |
| * @throws InvalidPropertyException | |
| */ | |
| protected function validateDateFormat(string $field, $data) | |
| { | |
| $this->validateIsScalar($field, $data); | |
| if (null === $data) { | |
| return; | |
| } | |
| try { | |
| new \DateTime($data); | |
| } catch (\Exception $e) { | |
| throw InvalidPropertyException::dateExpected( | |
| $field, | |
| \Datetime::ISO8601, | |
| static::class, | |
| $data | |
| ); | |
| } | |
| if (!preg_match('/^\d{4}-\d{2}-\d{2}/', $data)) { | |
| throw InvalidPropertyException::dateExpected( | |
| $field, | |
| \Datetime::ISO8601, | |
| static::class, | |
| $data | |
| ); | |
| } | |
| } | |
| /** | |
| * @param string $tagCode | |
| * | |
| * @throws InvalidPropertyException | |
| * | |
| * @return TagInterface | |
| */ | |
| protected function getTagByCode($tagCode) | |
| { | |
| $tag = $this->tagRepository->findOneByIdentifier($tagCode); | |
| if (null === $tag) { | |
| throw InvalidPropertyException::validEntityCodeExpected( | |
| 'tags', | |
| 'tag code', | |
| 'The tag does not exist', | |
| static::class, | |
| $tagCode | |
| ); | |
| } | |
| return $tag; | |
| } | |
| /** | |
| * @param string $categoryCode | |
| * | |
| * @throws InvalidPropertyException | |
| * | |
| * @return CategoryInterface | |
| */ | |
| protected function getCategoryByCode($categoryCode) | |
| { | |
| $category = $this->categoryRepository->findOneByIdentifier($categoryCode); | |
| if (null === $category) { | |
| throw InvalidPropertyException::validEntityCodeExpected( | |
| 'categories', | |
| 'category code', | |
| 'The category does not exist', | |
| static::class, | |
| $categoryCode | |
| ); | |
| } | |
| return $category; | |
| } | |
| /** | |
| * @param AssetInterface $asset | |
| * @param array $tags | |
| * | |
| * @throws InvalidPropertyException | |
| */ | |
| protected function removeTagsByCodes(AssetInterface $asset, array $tags) | |
| { | |
| foreach ($tags as $tagCode) { | |
| $asset->removeTag($this->getTagByCode($tagCode)); | |
| } | |
| } | |
| /** | |
| * @param AssetInterface $asset | |
| * @param array $categories | |
| * | |
| * @throws InvalidPropertyException | |
| */ | |
| protected function removeCategoriesByCodes(AssetInterface $asset, array $categories) | |
| { | |
| foreach ($categories as $categoryCode) { | |
| $asset->removeCategory($this->getCategoryByCode($categoryCode)); | |
| } | |
| } | |
| /** | |
| * @param AssetInterface $asset | |
| * @param bool $isLocalized | |
| * | |
| * @throws ImmutablePropertyException | |
| */ | |
| protected function setLocalized(AssetInterface $asset, $isLocalized) | |
| { | |
| if (null !== $asset->getId() && $asset->isLocalizable() !== $isLocalized) { | |
| throw ImmutablePropertyException::immutableProperty('localizable', $isLocalized, self::class); | |
| } | |
| $this->assetFactory->createReferences($asset, $isLocalized); | |
| } | |
| /** | |
| * @param string $field | |
| * @param mixed $data | |
| * | |
| * @throws InvalidPropertyTypeException | |
| */ | |
| protected function validateIsArrayOfScalar(string $field, $data): void | |
| { | |
| if (!is_array($data)) { | |
| throw InvalidPropertyTypeException::arrayExpected($field, static::class, $data); | |
| } | |
| foreach ($data as $key => $value) { | |
| if (null !== $value && !is_scalar($value)) { | |
| throw InvalidPropertyTypeException::validArrayStructureExpected( | |
| $field, | |
| sprintf('one of the "%s" values is not a scalar', $field), | |
| static::class, | |
| $data | |
| ); | |
| } | |
| } | |
| } | |
| /** | |
| * @param string $field | |
| * @param mixed $data | |
| * | |
| * @throws InvalidPropertyTypeException | |
| */ | |
| protected function validateIsScalar(string $field, $data): void | |
| { | |
| if (null !== $data && !is_scalar($data)) { | |
| throw InvalidPropertyTypeException::scalarExpected($field, static::class, $data); | |
| } | |
| } | |
| /** | |
| * @param string $field | |
| * @param mixed $data | |
| * | |
| * @throws InvalidPropertyTypeException | |
| */ | |
| protected function validateIsBoolean(string $field, $data): void | |
| { | |
| if (null !== $data && !is_bool($data)) { | |
| throw InvalidPropertyTypeException::booleanExpected($field, static::class, $data); | |
| } | |
| } | |
| } |